﻿//-----------------------------------------------------------------------
// <copyright file="ContentAggregationWebPart.cs" company="Microsoft 
// Corporation">
// Copyright (c) Microsoft Corporation.
// All rights reserved.
// THIS CODE AND INFORMATION ARE PROVIDED "AS IS" WITHOUT WARRANTY OF ANY 
// KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
// </copyright>
// <author>Anil Dwarakanath</author>
// <email>anildwa@microsoft.com</email>
// <date>31-Dec-2010</date>
// <summary>Main Class for Rendering WebPart Controls</summary>
//-----------------------------------------------------------------------

#region References

using System;
using System.ComponentModel;
using System.Web;
using System.Web.UI;
using System.Web.UI.WebControls;
using System.Web.UI.WebControls.WebParts;
using Microsoft.SharePoint;
using Microsoft.SharePoint.WebControls;
using Microsoft.SharePoint.WebPartPages;
using System.Xml.Serialization;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Web.UI.HtmlControls;
#endregion


namespace ContentAggregationWebPart
{

    public class ContentAggregationWebPart : Microsoft.SharePoint.WebPartPages.WebPart
    {

        #region Webpart Properties


        /// <summary>
        /// Site Collection Url
        /// </summary>
        [WebBrowsable(false),
        Category("Custom View Properties"),
        DefaultValue(""),
        Personalizable(PersonalizationScope.Shared),
        WebDisplayName("Site Collection Url"),
        WebDescription("")]
        public string SiteCollectionUrl
        {
            get;
            set;
        }



        /// <summary>
        /// View Fields
        /// </summary>
        [WebBrowsable(false),
        Category("Custom View Properties"),
        DefaultValue(""),
        Personalizable(PersonalizationScope.Shared),
        WebDisplayName(""),
        WebDescription("")]
        public List<string> ViewFields
        {
            get;
            set;
        }

        /// <summary>
        /// CAML Query
        /// </summary>
        [WebBrowsable(false),
       Category("Custom View Properties"),
       DefaultValue(""),
       Personalizable(PersonalizationScope.Shared),
       WebDisplayName(""),
       WebDescription("")]
        public string CamlQuery
        {
            get;
            set;
        }

        /// <summary>
        /// Group By Field Name
        /// </summary>
        [WebBrowsable(false),
     Category("Custom View Properties"),
     DefaultValue(""),
     Personalizable(PersonalizationScope.Shared),
     WebDisplayName(""),
     WebDescription("")]
        public string GroupBy
        {
            get;
            set;
        }


        /// <summary>
        /// SPGridView Page Size
        /// </summary>
        [WebBrowsable(false),
    Category("Custom View Properties"),
    DefaultValue(""),
    Personalizable(PersonalizationScope.Shared),
    WebDisplayName(""),
    WebDescription("")]
        public string PageSize
        {
            get;
            set;
        }


        /// <summary>
        /// Content Types
        /// </summary>
        [WebBrowsable(false),
       Category("Custom View Properties"),
       DefaultValue(""),
       Personalizable(PersonalizationScope.Shared),
       WebDisplayName(""),
       WebDescription("")]
        public List<string> ContentTypes
        {
            get;
            set;
        }


        /// <summary>
        /// SPGridView Display Column Names
        /// </summary>
        [WebBrowsable(false),
     Category("Custom View Properties"),
     DefaultValue(""),
     Personalizable(PersonalizationScope.Shared),
     WebDisplayName(""),
     WebDescription("")]
        public List<string> ExtendedDisplayColumns
        {
            get;
            set;
        }




        /// <summary>
        /// Site Collection Sub Sites 
        /// </summary>
        [WebBrowsable(false),
      Category("Custom View Properties"),
      DefaultValue(""),
      Personalizable(PersonalizationScope.Shared),
      WebDisplayName(""),
      WebDescription("")]
        public List<string> Webs
        {
            get;
            set;
        }

        /// <summary>
        /// Base Types for list templates
        /// </summary>
        public enum BaseListTypes
        {
            CustomList = 0,
            DocumentLibrary =1,
            DiscussionForum = 3,
            Surveys= 4,
            IssuesList = 5
            

        }


       



        /// <summary>
        /// SPSiteData Scope
        /// </summary>
        public enum Scope
        {
            SiteCollection,
            Web
            
        }


        /// <summary>
        /// SPSiteData Scope Property
        /// </summary>
        [WebBrowsable(true),
     Category("Custom View Properties"),
     DefaultValue(""),
     Personalizable(PersonalizationScope.Shared),
     WebDisplayName("Select Scope"),
     WebDescription("Select Scope")]
        public Scope SiteDataScope
        {
            get;
            set;
        }


        /// <summary>
        /// BaseListType Property
        /// </summary>
        [WebBrowsable(true),
     Category("Custom View Properties"),
     DefaultValue(""),
     Personalizable(PersonalizationScope.Shared),
     WebDisplayName("Select Base List Type"),
     WebDescription("Select Base List Type")]
        public BaseListTypes BaseListType
        {
            get;
            set;
        }

    #endregion

        #region Private Fields
        
        private SPGridView spgridview = new SPGridView();
        LiteralControl ItemCount = new LiteralControl();

        #endregion


        #region WebPart Events


        /// <summary>
        /// Is Called after the webpart control is initialized. 
        /// </summary>
        protected override void CreateChildControls()
        {
            LiteralControl message = new LiteralControl();

            if (SiteCollectionUrl == null || ViewFields == null || ExtendedDisplayColumns == null || ExtendedDisplayColumns.Count == 0)
            {
                message.Text = "WebPart is not Configured";
                this.Controls.Add(message);
                return;
            }

            try
            {
                AddScriptControl();
                CreateObjectDataSource();
                SetSPGridViewProperties(spgridview);
                PopulateGrid(spgridview);
                AddPagerControl();


            }
            catch (Exception ex)
            {
                message.Text = ex.ToString();
                this.Controls.Add(message);

            }
        }

        /// <summary>
        /// Renders HTML output to the response stream
        /// </summary>
        protected override void Render(HtmlTextWriter writer)
        {
            base.Render(writer);
        }


        /// <summary>
        /// Is called when the EditWebPart Property is opened
        /// </summary>
        public override ToolPart[] GetToolParts()
        {
            ToolPart[] toolparts = new ToolPart[3];
            WebPartToolPart wptp = new WebPartToolPart();
            CustomPropertyToolPart custom = new CustomPropertyToolPart();


            // This is the custom ToolPart.
            toolparts[1] = new ContentAggregationToolPart();
            toolparts[0] = custom;
            toolparts[2] = wptp;


            return toolparts;


        }
        #endregion


        #region SPGridViewEvents

        /// <summary>
        /// Is raised when the page index changed
        /// </summary>
        private void gridview_PageIndexChanging(object sender, GridViewPageEventArgs e)
        {

            spgridview.PageIndex = e.NewPageIndex;
            spgridview.DataBind();


        }

        /// <summary>
        /// Is Called when the when each row is bound to the datasource 
        /// </summary>
        private void spgridview_RowDataBound(object sender, GridViewRowEventArgs e)
        {
            if (e.Row.RowType != DataControlRowType.DataRow)
                return;

            int startCellIndex=0;

            if (GroupBy == "")
                startCellIndex = 0;
            else
                startCellIndex = 1;

            for (int i = startCellIndex; i <= e.Row.Cells.Count - 1; i++)
            {

                //if (spgridview.Columns[i].GetType() == typeof(SPMenuField))
                //    continue;


                foreach (string item in ExtendedDisplayColumns)
                {
                    ExtendedDisplayColumnType excol = (ExtendedDisplayColumnType)item.ToUserDefinedType<ExtendedDisplayColumnType>();
                    if (excol.Name == ((SPBoundField)spgridview.Columns[i]).DataField)
                    {

                        if (excol.IsHyperLink && excol.LinkUrl != "")
                        {
                            HyperLink linkUrl = new HyperLink();

                            if (((Label)e.Row.Cells[i].Controls[0]).Text == "")
                            {
                                linkUrl.Text = "Empty";
                            }
                            else
                            {
                                linkUrl.Text = ((Label)e.Row.Cells[i].Controls[0]).Text;
                            }
                            if (excol.LinkUrl == "FileRef")
                            {
                                linkUrl.NavigateUrl = GetFileRefUrl(e.Row);
                            }
                            else
                            {
                                linkUrl.NavigateUrl = string.Format(excol.LinkUrl, ((Label)e.Row.Cells[i].Controls[0]).Text);
                            }

                            e.Row.Cells[i].Controls.Clear();
                            e.Row.Cells[i].Controls.Add(linkUrl);
                            if (excol.IsClickToExpand)
                            {
                                AddPreviewControl(e.Row.Cells[i], linkUrl.NavigateUrl, e.Row.RowIndex, i);
                            }



                        }


                    }
                }

            }
        }

        #endregion


        #region DataSource Methods
        /// <summary>
        /// Is invoked when the DataSource object is being created
        /// </summary>
        private void objDataSrc_ObjectCreating(object sender, ObjectDataSourceEventArgs e)
        {
            e.ObjectInstance = this;
        }

        /// <summary>
        /// Is called by the SPGridView DataSource property
        /// </summary>
        private void CreateObjectDataSource()
        {
            ObjectDataSource objDataSource = new ObjectDataSource();
            objDataSource.ID = "AggregatedDataSource";
            objDataSource.SelectMethod = "GetSubSiteData";
            objDataSource.TypeName = this.GetType().AssemblyQualifiedName;
            objDataSource.ObjectCreating += new ObjectDataSourceObjectEventHandler(objDataSrc_ObjectCreating);
            this.Controls.Add(objDataSource);
        }
        #endregion



        #region Private Methods


        /// <summary>
        /// Add javascript functions to the webpart page
        /// </summary>
        private void AddScriptControl()
        {
            LiteralControl scriptControl = new LiteralControl();
            scriptControl.Text = @"<script src='../_layouts/Scripts/jquery-1.4.1.js' type='text/javascript'>
                                    </script>
                                    <script type='text/javascript'>
                                                  $(document).ready(function()
                                                { 
                                                        

                                                 }); 

                                                function toggle(id,url) {
                                                if($('#' + id).find('iframe').attr('src') == '')
                                                $('#' + id).find('iframe').attr('src', url);
                                                $('#' + id).toggle('fast');
                                                }

                                    </script>";
            this.Controls.Add(scriptControl);


        }


        /// <summary>
        /// Adds URL preview control to SPGridView Cells
        /// </summary>
        /// <param name="cell">cell where the preview control is added</param>
        /// <param name="url">Url that needs to shown in the preview</param>
        /// <param name="rowindex">spgridview row being bound</param>
        /// <param name="cellIndex">spgridview cell being bound</param>
        protected void AddPreviewControl(TableCell cell, string url, int rowIndex, int cellIndex)
        {

            LiteralControl newLine = new LiteralControl("<br/>");

            cell.Controls.Add(newLine);

            string id = "div_" + rowIndex + cellIndex;

            ((HyperLink)cell.Controls[0]).NavigateUrl = "javascript: toggle('" + id + "','" + url + "');";


            LiteralControl newLine1 = new LiteralControl("<br>");

            cell.Controls.Add(newLine1);


            LiteralControl iframe = new LiteralControl(@"<div id='" + id + "' style='border: 1px solid silver;display:none;width:500px;height:300px'><iframe  scrolling='yes'  frameborder='0' src='' width='100%' height='100%'></iframe></div>");


            cell.Controls.Add(iframe);

        }

        /// <summary>
        /// Gets the URL from the datatable which contains column name FileRef
        /// </summary>
        /// <param name="row">spgridview row being bound</param>
        private string GetFileRefUrl(GridViewRow row)
        {

            for (int i = 1; i <= row.Cells.Count - 1; i++)
            {

                if (((SPBoundField)spgridview.Columns[i]).DataField == "FileRef")
                {

                    if(((Label)row.Cells[i].Controls[0]).Text.Contains("_.000"))
                    {
                        return GetListDisplayForm(((Label)row.Cells[i].Controls[0]).Text);
                    }
                    else
                    {
                         return ((Label)row.Cells[i].Controls[0]).Text;
                    }
                        
                         
                   
                }

            }

            return "";

        }


        /// <summary>
        /// Populates the display form url if the FileRef is a CustomList Item
        /// </summary>
        /// <param name="row">spgridview row being bound</param>
        private string GetListDisplayForm(string FileRef)
        {



            return string.Format("{0}/dispform.aspx?ID={1}", FileRef.Substring(0, FileRef.LastIndexOf("/")),
                FileRef.Substring(FileRef.LastIndexOf("/") + 1).Substring(0, FileRef.Substring(FileRef.LastIndexOf("/") + 1).LastIndexOf("_.000")));

        }


        /// <summary>
        /// Creates the the datagrid columns
        /// </summary>
        /// <param name="datagrid">SPGridView on the webpart</param>
        private void PopulateGrid(SPGridView datagrid)
        {
            foreach (string item in ExtendedDisplayColumns)
            {
                ExtendedDisplayColumnType excol = (ExtendedDisplayColumnType)item.ToUserDefinedType<ExtendedDisplayColumnType>();

                SPBoundField spgridviewColumn = new SPBoundField();
                spgridviewColumn.HeaderText = excol.Title;
                spgridviewColumn.DataField = excol.Name;
                spgridviewColumn.Visible = excol.IsVisible;
                datagrid.Columns.Add(spgridviewColumn);

            }


            //this.Controls.Add(datagrid);

        }

        /// <summary>
        /// Creates HTML formatted controls and renders the SPGridView Pager controls
        /// </summary>
        private void AddPagerControl()
        {

            HtmlTable mainTable = new HtmlTable();
            mainTable.CellSpacing = 0;


            HtmlTableRow topRow = new HtmlTableRow();
            topRow.BgColor = "silver";

            HtmlTableRow middleRow = new HtmlTableRow();


            HtmlTableRow bottomRow = new HtmlTableRow();
            bottomRow.BgColor = "silver";


            HtmlTableCell topCell1 = new HtmlTableCell();
            topCell1.Align = "left";


            HtmlTableCell topCell2 = new HtmlTableCell();
            topCell2.Align = "right";

            HtmlTableCell middleCell = new HtmlTableCell();
            //middleCell.Align = "left";

            HtmlTableCell bottomCell = new HtmlTableCell();
            bottomCell.Align = "center";





            topCell1.Controls.Add(ItemCount);

            topRow.Cells.Add(topCell1);

            SPGridViewPager topPager = new SPGridViewPager();
            topPager.ID = "pager1";
            topPager.GridViewId = spgridview.ID;

            SPGridViewPager bottomPager = new SPGridViewPager();
            bottomPager.ID = "pager2";
            bottomPager.GridViewId = spgridview.ID;

            topCell2.Controls.Add(topPager);

            topRow.Cells.Add(topCell2);

            middleCell.Controls.Add(spgridview);

            middleRow.Cells.Add(middleCell);


            bottomCell.Controls.Add(bottomPager);

            bottomRow.Cells.Add(bottomCell);


            mainTable.Rows.Add(topRow);
            mainTable.Rows.Add(middleRow);
            mainTable.Rows.Add(bottomRow);

            this.Controls.Add(mainTable);

        }



        /// <summary>
        /// Sets SPGridView properties 
        /// </summary>
        private void SetSPGridViewProperties(SPGridView gridview)
        {

            gridview.ID = "spGridView";
            gridview.AutoGenerateColumns = false;
            gridview.EnableViewState = false;

            if (GroupBy != null && GroupBy != "")
            {
                gridview.AllowGrouping = true;
                gridview.AllowGroupCollapse = true;
                gridview.GroupField = GroupBy;
            }

            if (PageSize != null && PageSize != "")
            {
                gridview.PageSize = Convert.ToInt32(PageSize);
                gridview.AllowPaging = true;
                gridview.PageIndexChanging += new GridViewPageEventHandler(gridview_PageIndexChanging);

            }

            gridview.AllowSorting = true;
            gridview.AllowFiltering = true;


            string columnString = "";

            foreach (string item in ExtendedDisplayColumns)
            {
                columnString += ((ExtendedDisplayColumnType)item.ToUserDefinedType<ExtendedDisplayColumnType>()).Name + ",";
            }

            gridview.FilterDataFields = columnString;
            gridview.FilteredDataSourcePropertyName = "FilterExpression";
            gridview.FilteredDataSourcePropertyFormat = "{1} LIKE '{0}'";

            gridview.DataSourceID = "AggregatedDataSource";


            gridview.RowDataBound += new GridViewRowEventHandler(spgridview_RowDataBound);
        }



   

        #endregion

    
        #region Data Aggregation


        /// <summary>
        /// Invokes the GetSiteData Method on the selected webs or on the site collection root web
        /// </summary>
        public DataTable GetSubSiteData()
        {
            DataTable sitedata = null;
            SPWeb web = null;
            SPSecurity.RunWithElevatedPrivileges(delegate()
            {
                using (SPSite site = new SPSite(SiteCollectionUrl))
                {
                    SPSiteDataQuery query = new SPSiteDataQuery();
                    query.Lists = string.Format("<Lists BaseType='{0}'/>", (int)(BaseListType));

                    query.Query = CamlQuery;

                    foreach (string item in ViewFields)
                    {
                        query.ViewFields += string.Format("<FieldRef Name=\"{0}\" Type=\"{1}\" Nullable='TRUE' />",
                            ((BaseSPType)item.ToUserDefinedType<BaseSPType>()).Name, ((BaseSPType)item.ToUserDefinedType<BaseSPType>()).Type);
                    }

                    if (SiteDataScope == Scope.SiteCollection)
                    {
                        query.Webs = "<Webs Scope=\"SiteCollection\" />";
                        web = site.RootWeb;
                        sitedata = web.GetSiteData(query);
                    }
                    else if (SiteDataScope == Scope.Web)
                    {
                        query.Webs = "<Webs Scope=\"Web\" />";
                        //web = site.AllWebs[5];
                        sitedata = GetWebData(site, query);

                    }



                }
            });


            CleanDataTable(sitedata);

            if (GroupBy != null && GroupBy != "")
                sitedata.DefaultView.Sort = GroupBy;

            ItemCount.Text = string.Format("Item Count:{0}", sitedata.Rows.Count.ToString());

            return sitedata.DefaultView.ToTable();
        }


        /// <summary>
        /// Creates the the datagrid columns
        /// </summary>
        /// <param name="datagrid">SPGridView on the webpart</param>
        private DataTable GetWebData(SPSite site, SPSiteDataQuery query)
        {
            DataTable webdata = new DataTable();

            foreach (string item in Webs)
            {
                SPWeb web = site.AllWebs[new Guid(((BaseSPType)item.ToUserDefinedType<BaseSPType>()).Guid)];
                webdata.Merge(web.GetSiteData(query));


            }

            return webdata;


        }


        /// <summary>
        /// Removes sharepoint item delimiters in the GetS
        /// </summary>
        /// <param name="datagrid">SPGridView on the webpart</param>
        private void CleanDataTable(DataTable dt)
        {
            foreach (DataRow row in dt.Rows)
            {
                foreach (DataColumn col in dt.Columns)
                {
                    if (row[col].ToString().Contains(";#"))
                        row[col] = row[col].ToString().Split(new string[] { ";#" }, StringSplitOptions.None)[1];
                    if (col.ColumnName == "FileRef")
                    {
                        row[col] = "/" + row[col];
                    }

                }

            }
        }
        #endregion


    }


   

}
